<?php
/**
 * 命名：新浪微博的id命名为weibo_id，如果在token中，一律命名为uid
 * 
 * @author Leon
 *
 */
class data_weibo extends data_social {
	private $akey;
	private $skey;
	private $authorize_url;

	public function __construct ( ) {
		if (defined('WB_AKEY') and defined('WB_SKEY') ) {
			$this->akey			= WB_AKEY;
			$this->skey			= WB_SKEY;
			$this->authorize_url	= WB_AUTHORIZE_URL;
			
			parent::__construct();
		}
	}
	/** 获取登陆的url
	 *
	 * @return String
	 */
	public function authorize_url ($flag = 'iframe/setting') {
		if ($this->akey) {
			$params = array (
				'client_id'		=> $this->akey,
				'redirect_uri'	=> data_social::make_callback_url(),
				'response_type'	=> 'code',
				'state'		=> data_social::make_state('weibo', $flag),
				'forcelogin'		=> false,
				'display'		=> NULL,
			);
			return $this->authorize_url . "?" . http_build_query ( $params );
		} else return false;
	}
	public function code_2_token($code) {
		if ($this->akey and $code) {
			$sae_auth = new SaeTOAuthV2($this->akey, $this->skey);
			$api_param = array (
				'code'		=> $code,
				'redirect_uri'	=> data_social::make_callback_url(),
			);
			$api_result = $sae_auth->getAccessToken('code', $api_param);				// 用code换token ("access_token", "expires_in", "uid")
			if ($api_result['access_token'] and $api_result['uid']) {					// 授权成功
				// 获取微博用户的nickname
				$weibo_user = $this->get_user_info($api_result['uid'], $api_result['access_token']);	// 返回(id,screen_name,...)
				if ($weibo_user) {
					$weibo_user['screen_name'] = ($weibo_user['screen_name']) ? $weibo_user['screen_name'] : $api_result['uid'];		// 没有screen name就用uid来代替吧
					// 重新整理token字段
					return array (
						'uid'			=> $api_result['uid'],
						'access_token'	=> $api_result['access_token'],
						'refresh_token'	=> $api_result['refresh_token'],			// 当前的新浪微博没有这个字段
						'ctime'		=> time(),
						'expires_in'		=> $api_result['expires_in'],
						'name'		=> $weibo_user['screen_name'],
						'nick'			=> $weibo_user['screen_name'],
					);
				} else {
					// 在get user info中已经记录了错误
					return false;
				}
			} else {
				new data_error_devel('新浪微博code to token错误', array('code'=>$code, 'api_result'=>$api_result), __CLASS__, __FUNCTION__, __LINE__);
				return false;
			}
		} return false;
	}
	/**
	 * 去微博api验证token的有效性
	 * 
	 * @param Array $token_from_db
	 * @param Int $offset_sec
	 * @return Array = array (access_token, refresh_token, scope, uid)
	 */
	public function token_valid_or_refresh_into_db ($token_from_db, $offset_sec=0) {
		$offset_sec = intval($offset_sec);
		
		if (is_array($token_from_db) and isset($token_from_db['access_token'])) {
			// 检查token是否有效
			$api_result = $this->is_token_valid($token_from_db['access_token'], $offset_sec);		// (uid, appkey, scope, create_at, expires_in)
			if ($api_result) {
				// 更新token中的时间记录，重新写入数据库
				$token_from_db['ctime']		= time();
				$token_from_db['expires_in']		= $api_result['expires_in'];
				$this->save_token('weibo', $token_from_db);
				return $token_from_db;
			} else {												// token 过期啦
				// 本来这里应该refresh token的，可是新浪微博不支持，只能返回false了
				$token_to_db = array (
					'uid'			=> $token_from_db['uid'],
					'ctime'		=> time()
				);
				$this->save_token('weibo', $token_to_db);		// 写入数据库
				new data_error_devel('微博get token info 错误，可能是token过期了', array ('token_from_db'=>$token_from_db, 'api_result'=>$api_result), __CLASS__, __FUNCTION__, __LINE__);
				return false;
			}
		} else return false;
	}
	private function is_token_valid ($access_token, $offset_sec=0) {
		// 用token info来检查access token 的有效性
		$sae_auth = new SaeTOAuthV2($this->akey, $this->skey);
		$api_param = array (
			'access_token' => $access_token
		);
		$api_result = json_decode($sae_auth->oAuthRequest('https://api.weibo.com/oauth2/get_token_info', 'POST', $api_param), true);	// (uid, appkey, scope, create_at, expires_in)
		// ## 修正新浪的拼写错误 ####################################################################
		$api_result['expires_in'] = ($api_result['expires_in']) ? $api_result['expires_in'] : $api_result['expire_in'];
		// ## 修正结束 ############################################################################
		
		if ($api_result['uid'] and $api_result['expires_in'] > $offset_sec) {
			return $api_result;
		} else {
			return false;
		}
	}
	/**
	 * 从数据库中读出access token，然后去微博api验证有效性
	 *		如果超时了，没法更新，只能返回false
	 * 
	 * @param Int $uid
	 * @param Int $offset_sec
	 * @return Array = array (access_token, refresh_token, uid, ctime)
	 */
	public function get_token ($uid, $offset_sec=0) {
		$offset_sec	= intval($offset_sec);
		
		$data_user = new data_user();
		$user = $data_user->one($uid);
		
		return $this->token_valid_or_refresh_into_db($user['weibo_token'], $offset_sec);
	}
	/**
	 * 获得当前登录的微博用户的互粉好友名单，循环读取，直至取完为止
	 * 
	 * @param int $uid
	 * @param string $token	// 如果存在，则去API读取，否则在cache中读取
	 * @return array = array (
	 *         array (
	 *         		weibo_id	=> // weibo_id
	 *         		nickname	=> // screen_name
	 *         )
	 */
	public function get_friends ($uid, $token='') {
		$uid		= intval($uid);
		$limit		= 50;
		if ($uid) {
			if ($token) {
				$sae_client = new SaeTClientV2($this->akey, $this->skey, $token['access_token']);
				$api_result = $sae_client->bilateral($token['uid'], 1, $limit, 0);
				if (is_array($api_result) and $api_result['users']) {
					$return = $api_result['users'];
					if ($api_result['total_number'] > $limit) {
						$max = ceil($api_result['total_number'] / $limit);
						for($i = 2; $i <= $max; $i++) {
							$api_result = $sae_client->bilateral($token['uid'], $i, $limit, 0);
							$return = array_merge($return, $api_result['users']);
						}
					}
					$return = $this->friends_to_simple($return);
					$this->cache_write($uid, 'weibo', 'friends', $return);
					return $return;
				} else {
					new data_error_devel('从API读取微博好友时出错，或者这人没有好友？', array('uid'=>$uid, 'token'=>$token, 'api_result'=>$api_result), __CLASS__, __FUNCTION__, __LINE__);
					return false;
				}
			} else {
				$cache = $this->cache_read($uid, 'weibo', 'friends');
				if ($cache) {
					return $cache;
				} else {
					return false;
				}
			}
		} else return false;
	}
	/**
	 * 简化friends记录，只返回weibo_id和nickname
	 * 
	 * @param Array $array
	 * @return Array
	 */
	private function friends_to_simple ($array) {
		if (is_array($array)) {
			foreach ( $array as $k => $v ) {
				$array[$k] = array (
						'weibo_id' 	=> trim($v['id']),
						'nickname' 	=> ($v['screen_name']) ? trim($v['screen_name']) : trim($v['id'])
				);
			}
			return $array;
		} else	return false;
	}

	/**
	 * 根据微博id获取微博用户的详细资料
	 *	只在新用户注册的时候使用，所以不用读cache，但是可以写入cache
	 *
	 * @param BigInt $weibo_id
	 * @param string $access_token 
	 * @return array = array (
	 *         "id": 1404376560,
	 *         "screen_name": "zaku",
	 *         "name": "zaku",
	 *         "province": "11",
	 *         "city": "5",
	 *         "location": "北京 朝阳区",
	 *         "description": "人生五十年，乃如梦如幻；有生斯有死，壮士复何憾。",
	 *         "url": "http://blog.sina.com.cn/zaku",
	 *         ..................
	 *         )
	 */
	public function get_user_info ($weibo_id, $access_token) {
		if ($access_token) {
			$sae_client = new SaeTClientV2($this->akey, $this->skey, $access_token);
			$api_result = $sae_client->show_user_by_id($weibo_id);
			if ($api_result['id']) {
				// 简化数组
				return array (
					'weibo_id'		=> $api_result['id'],
					'screen_name'	=> $api_result['screen_name'],
					'name'		=> $api_result['name'],
					'province'		=> $api_result['province'],
					'city'			=> $api_result['city'],
					'location'		=> $api_result['location'],
					'url'			=> $api_result['url'],
				);
			} else {
				new data_error_devel('新浪微博get user info错误', array('weibo_id'=>$weibo_id, 'access_token'=>$access_token, 'api_result'=>$api_result), __CLASS__, __FUNCTION__, __LINE__);
				return false;
			}
		} else return false;
	}
	public function shorturl ($url_long, $access_token) {
		if ($url_long and $access_token) {
			$o = new SaeTOAuthV2($this->akey, $this->skey, $access_token);
			$api_param = array (
				'access_token'	=> $access_token,
				'url_long'		=> $url_long 
			);
			$api_result = json_decode($o->oAuthRequest('https://api.weibo.com/2/short_url/shorten.json', 'GET', $api_param), true);
			if ($api_result['urls'][0]['url_short']) {
				return $api_result['urls'][0]['url_short'];
			} else {
				return $url_long;
			}
		} else {
			return $url_long;
		}
	}
	/**
	 * 发布一条微博
	 * 
	 * @param String $msg        	
	 * @param String $access_token        	
	 * @return Array
	 */
	public function post ($msg, $access_token) {
		if ($msg and $access_token) {
			if (mb_strlen($msg) < 141) {
				$sae_client = new SaeTClientV2($this->akey, $this->skey, $access_token);
				$api_result = $sae_client->update($msg);

				if ($api_result['id']) {
					return $api_result;
				} else new data_error_devel('发布微博出错', array ('access_token' => $access_token,'api_result' => $api_result), __CLASS__, __FUNCTION__, __LINE__);
			} else new data_error_devel('微博正文太长了', array ('msg' => $msg), __CLASS__, __FUNCTION__, __LINE__);
		} else new data_error_devel('msg或者access token为空', array('msg'=>$msg, 'access_token'=>$access_token), __CLASS__, __FUNCTION__, __LINE__);
		return false;
	}
	/**
	 * 评论一条微博
	 * @param BigInt $weibo_post_id
	 * @param String $msg
	 * @param String $access_token
	 * @return Array
	 */
	public function recomment ($weibo_post_id, $msg, $access_token) {
		if ($weibo_post_id and $msg and $access_token) {
			if (mb_strlen($msg) < 140) {
				$sae_client = new SaeTClientV2($this->akey, $this->skey, $access_token);
				$api_result = $sae_client->send_comment($weibo_post_id, $msg);		// 发布评论
				if ($api_result['id']) {
					return $api_result;
				} else new data_error_devel('微博评论出错', array('weibo_post_id' => $weibo_post_id, 'msg' => $msg, 'access_token'=>$access_token, 'api_result'=>$api_result), __CLASS__, __FUNCTION__, __LINE__);
			} else new data_error_devel('微博评论太长了', array ('msg' => $msg), __CLASS__, __FUNCTION__, __LINE__);
		} else new data_error_devel('参数不完整', array('weibo_post_id' => $weibo_post_id, 'msg' => $msg, 'access_token'=>$access_token), __CLASS__, __FUNCTION__, __LINE__);
		return false;
	}
// ###### V7 ###### ###### V7 ###### ###### V7 ###### ###### V7 ###### ###### V7 ###### ###### V7 ###### ###### V7 ###### 





	public function repost ($weibo_update_id, $msg, $access_token) {
		if ($weibo_update_id and $access_token) {
			$sae_client = new SaeTClientV2($this->akey, $this->skey, $access_token);
			$api_result = $sae_client->repost($weibo_update_id, $msg, 1);		// 发布转帖
			if ($api_result['id']) {
				return $api_result;
			} else {
				new data_error_devel('微博转发出错', array('api_result'=>$api_result), __CLASS__, __FUNCTION__, __LINE__);
				return false;
			}
		} return false;
	}
	
	


}
?>